home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / H-K / Infinity Windoid / Windoid.c < prev    next >
Encoding:
Text File  |  1993-03-02  |  39.0 KB  |  1,218 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  
  3.     NAME:
  4.         Infinity Windoid 2.2
  5.  
  6.     WRITTEN BY:
  7.         Troy Gaul
  8.         Infinity Systems
  9.  
  10.         © 1991-93 Infinity Systems
  11.         All rights reserved.
  12.  
  13.     DESCRIPTION:
  14.         This file contains the source for a standalone code resource that
  15.         conforms to a Window DEFinition (WDEF), as defined by Apple Computer 
  16.         in Inside Macintosh.
  17.         
  18.         It provides a 'windoid' appearance. A windoid is a floating window
  19.         that appears above document windows in an application and is commonly
  20.         used for things like tool palettes, information windows, and the like.
  21.         
  22.         The WDEF included in the ResEdit file can be used as-is, but if a zoom
  23.         box is to be used, you will probably want to change the behavior of
  24.         what is included (by default, it zooms smaller rather than larger as
  25.         described below). This WDEF is created for System 6 and later, but it 
  26.         would be easy to modify it for earlier systems if this is important.
  27.  
  28.     FEATURES:
  29.         •    Supports System 7-style coloring of windows.
  30.         •    In System 7, the tinge color set by the user in the Color control 
  31.             panel is used.
  32.         •    Close box can be enabled from NewWindow by setting goAwayFlag.
  33.         •    Zoom box (special case) implemented, utilized by adding zoomDocProc
  34.             to the proc ID used to create the windoid.
  35.         •    Title bar can appear along the left of the window if 1 is added to 
  36.             the proc ID (with or without a zoom box).
  37.         •    For MacApp users, the left/top behavior of the proc ID can be 
  38.             switched.
  39.         •    System 6 coloring scheme is also supported (can be set in Kolor or
  40.             a similar control panel).
  41.         •    In System 7, DeviceLoop is used so the windoid will be drawn 
  42.             correctly even when it crosses monitors of differing depths.
  43.         •    In System 7, indexed color tables are checked to see if there are
  44.             enough different colors to display the color version (like the 
  45.             system WDEF).
  46.         
  47. -------------------------------------------------------------------------------
  48.  
  49.     VERSION HISTORY:
  50.         2.2: (Mar 93)
  51.             •    First publicly distributed version.
  52.             •    Extensive comments added to facilitate understanding and
  53.                 modification by others.
  54.             •    Added support for MacApp-style varcodes.
  55.             •    Bug in way inColor was determined (needed to do a bit-shift
  56.                 before anding with gdFlags) fixed.
  57.             •    Removed StuffHex of strings used for title bar pattern, now
  58.                 calculates these values.
  59.             •    Fixed bug in logic of how MixColor was calculating the mixture.
  60.             •    Support for compilation in THINK C 5.0.
  61.             •    Added way to build so the window are always hilighted
  62.  
  63.         2.1: (Nov 92)
  64.             •    Reduced code size by making sure no extra code was being linked
  65.                 by MPW.
  66.             •    Removed use of Gestalt for code size reasons.
  67.             •    Ended the use of function pointers since no advantage was being
  68.                 gained by their use.
  69.             •    Added support for determining if enough different colors were
  70.                 available to do System 7-style color like Apple's does.
  71.  
  72.         2.0: (January 92)
  73.             •    Rewritten in C.
  74.             •    Conditional compilation of some features to facilitate a 
  75.                 reduced-size version and one that could be distributed.
  76.  
  77.         1.2: (June 91)
  78.             •    System 6 color support added. This feature was suggested by
  79.                 Richard R. Harms.
  80.             •    DeviceLoop support added. (Thanks, MacDTS.)
  81.  
  82.         1.1: (May 91)
  83.             •    Support for System 7-style color titlebars.
  84.  
  85.         1.0: (May 91)
  86.             •    Original version, written in Pascal and based on original
  87.                 assembly language, black-and-white windoid WDEF used in
  88.                 MicroFrontier products, which was written by Tom Pinkerton.
  89.  
  90. -------------------------------------------------------------------------------
  91.  
  92.     MAKING WINDOWS FLOAT:
  93.         I just wanted to point out that the windoid WDEF provided here will
  94.         simply give you a window with a smaller, palette-style titlebar. It
  95.         does NOT make that window float above all the others in your program.
  96.         This behavior (which is almost always associated with windows using
  97.         this sort of WDEF) must be implemented into the application's window-
  98.         handling code. This is not necessarily a straightforward thing to do,
  99.         as there is no easy, Apple-provided way. It is not difficult, but some
  100.         care must be taken.
  101.  
  102.     RELEASE/USAGE INFORMATION:
  103.         This WDEF is used in commercial applications by MicroFrontier, Inc.,
  104.         including (but not limited to) Enhance 2.0, Color It! 2.0, and Paint
  105.         It! 1.0.
  106.  
  107.         MicroFrontier and I are hereby making this WDEF available for use in 
  108.         other products, commercial or not, with the understanding that you may
  109.         modify the code in whatever ways are necessary for use in your
  110.         product (such as adding a grow box, changing zoom behavior, etc).
  111.         MicroFrontier and Troy Gaul, however, will take no responsibility
  112.         for problems caused by the use of this code.
  113.  
  114.         If you do have any problems, though, don't be afraid do contact me
  115.         by one of the ways listed below. I'll be glad to help. Also, if
  116.         you make modifications to the WDEF, I would appreciate it if you
  117.         would let me know about them. If there are changes that might benefit
  118.         others, I might implement them for a future release.
  119.         
  120.         I do plan to support this WDEF in the future. If you have problems,
  121.         compatibility or otherwise, or if you see a glaring error in the code,
  122.         let me know, and a revision will be made. I will also keep a list of
  123.         e-mail addresses of those people who tell me they are using the
  124.         WDEF and want to receive updates. When a new version is released,
  125.         it (or at least notification of it) will be sent to all such users.
  126.         
  127.     ACKNOWLEDGEMENTS:
  128.         I'd like to pay special thanks to Tom Pinkerton, who wrote a windoid
  129.         WDEF from which I created this one and who taught me how to program the
  130.         Macintosh, and to Richard Harms, who kept pushing me to add features 
  131.         (such as the System 6 color support, support for 68000 machines, and 
  132.         the MacApp-style), told me about the bugs he found, and prodded me to 
  133.         release a version to the public. Also, thanks to MicroFrontier for
  134.         letting me release this WDEF for use by others.
  135.  
  136. -------------------------------------------------------------------------------
  137.  
  138.     HOW TO CONTACT THE AUTHOR:
  139.         To 'register' your copy of this WDEF if you plan to use it and want
  140.         updates in the future, send me your e-mail address(es). Also, use
  141.         these to contact me with any problems.
  142.  
  143.         Troy Gaul
  144.         Infinity Systems
  145.         1101 25th Street, #5
  146.         Des Moines, IA 50311
  147.         (515) 255-2080
  148.         
  149.         MicroFrontier, Inc.
  150.         3401 101st Street
  151.         Suite E
  152.         Des Moines, IA 50322
  153.         (515) 270-8109
  154.         
  155.         Internet:            tag002@acad.drake.edu (until May 93)
  156.                                 t-gaul@grayhawk.rent.com
  157.                                 ntwing@aol.com
  158.                                 mfrontier@applelink.apple.com
  159.                                 mfrontier@aol.com
  160.                         
  161.         Applelink:            mfrontier
  162.         
  163.         America Online:    ntwing
  164.                                 mfrontier
  165.                                 
  166.         FAX:                    (515) 278-6828
  167.  
  168. ******************************************************************************/
  169.  
  170.  
  171. //*****************************************************************************
  172. //        Include files
  173. //-----------------------------------------------------------------------------
  174.  
  175. #define SystemSixOrLater 1        
  176.     // This is used so that we can cut down on the code size in MPW. If you 
  177.     // think support for earlier systems is important, get rid of this, but
  178.     // make sure you do your own testing, I have not tried it with any earlier
  179.     // systems. 
  180.     //    Note: for this define to work under THINK C, MacHeaders should NOT
  181.     // be included (and are not in the included project file).
  182.  
  183. //-----------------------------------------------------------------------------
  184.  
  185. #include <Memory.h>
  186. #include <QuickDraw.h>
  187. #include <OSUtils.h>
  188. #include <Windows.h>
  189. #include <Palettes.h>
  190. #include <ToolUtils.h>
  191. #include <Desk.h>
  192.  
  193. //*****************************************************************************
  194. //        Conditional Compilation Options
  195. /*-----------------------------------------------------------------------------
  196.  
  197.     The #define's you may make include:
  198.  
  199.         MFI_ZOOMBOX -  This is the special behavior of the zoombox in palettes
  200.                             in products from MicroFrontier, Inc. This involves
  201.                             shrinking the palette to the titlebar + a strip that
  202.                             will show the palette's name (note: this requires some
  203.                             special application coding to implement). Also, the code
  204.                             inclosed in these conditionals may be a good start for
  205.                             coding your own zoom routines.
  206.         
  207.         ALLOW_VERT -    This determines if the code that is compiled will support
  208.                             a palette that has a vertical title bar along the left
  209.                             side of the window (rather than the top). To create such
  210.                             a window, add one to the varcode that is used.
  211.         
  212.         MACAPP_STYLE - This determines if the varcodes that are supported are
  213.                             the one's I consider 'normal' or the ones MacApp's
  214.                             windoid WDEF knows about. Note, however, that this code
  215.                             only supports the 'smaller', title-less version that
  216.                             is available in MacApp's.
  217.  
  218.         ALWAYS_HILITE    This will cause a windoid to be created that will always
  219.                             draw its title bar with gadgets and all. Normally, the
  220.                             windoid will draw the titlebar and frame in gray and
  221.                             empty when the window is not hilighted (like normal
  222.                             windows). Some programs, however, don't keep their
  223.                             windoids properly hilighted, so this will make them 
  224.                             appear to always be active.
  225.  
  226. -----------------------------------------------------------------------------*/
  227.  
  228. #define MFI_ZOOMBOX
  229. #define ALLOW_VERT
  230.  
  231. //*****************************************************************************
  232. //        Constants
  233. //-----------------------------------------------------------------------------
  234.  
  235. #define    wpTitleHeight    11
  236.     // This is the height of the windoid's titlebar.
  237.  
  238. #define    wpSmallZoom        12
  239.     // This is the size of the area under (or right of) the title bar when the
  240.     //    MFI zoombox is in its reduced mode.
  241.     
  242. //-----------------------------------------------------------------------------
  243. //        Color table tinge percentage constants    
  244.  
  245. #define    wTitleBarLightPct        0x01
  246. #define    wTitleBarDarkPct        0x08
  247. #define  wCloseBoxColor            0x05
  248. #define    wXedBoxPct                0x08
  249. #define    wInactiveFramePct        0x0A
  250.  
  251. //-----------------------------------------------------------------------------
  252. //        Color table constants    
  253.  
  254. enum {
  255.     wHiliteColorLight    =  5, 
  256.     wHiliteColorDark,
  257.     wTitleBarLight,
  258.     wTitleBarDark,
  259.     wDialogLight,
  260.     wDialogDark,
  261.     wTingeLight,
  262.     wTingeDark
  263. };
  264.     // These are the constants defined in the Apple technical note regarding
  265.     // Color, Windows, and System 7. Last I checked, they weren't in an Apple
  266.     // header file. (But the ones < 5 are, from the previous, pre-System 7
  267.     // coloring scheme.)
  268.  
  269. //-----------------------------------------------------------------------------
  270. //        Style variation constants    
  271.  
  272. enum {
  273.     blackandwhite    = 0,
  274.     sys7color,
  275.     sys6color
  276. };
  277.     // These constants represent the three types of window 'colorings' we
  278.     // support.
  279.     
  280. //-----------------------------------------------------------------------------
  281. //        MacApp style variations    
  282.  
  283. #define kMacApp_toggleTBar        0x01    // bit 0 tells us whether to hilite/unhilite title bar
  284. #define kMacApp_hasTallTBar    0x02    // bit 1 is tall title bar bit (unsupported)
  285. #define kMacApp_hasGrow            0x04    // bit 2 is grow bit (unsupported)
  286. #define kMacApp_hasZoom            0x08    // bit 3 is zoom bit
  287.  
  288. //*****************************************************************************
  289. //        Structures
  290. //-----------------------------------------------------------------------------
  291.  
  292. typedef struct WindoidData {
  293.     WStateData    wState;
  294.     unsigned int            closeToggle : 1;
  295.     unsigned int            isSystem7     : 1;
  296.     unsigned int            hasCQD        : 1;
  297.     unsigned int            isHoriz         : 1;
  298.     unsigned int            ignoreHilite: 1;
  299. #ifdef MFI_ZOOMBOX
  300.     unsigned int            zoomToggle     : 1;
  301.     unsigned int            hasZoom         : 1;
  302. #endif
  303. } WindoidData, *WindoidDataPtr, **WindoidDataHandle;
  304.  
  305. #define WindData (**(WindoidDataHandle)(theWindow->dataHandle))
  306.     // This macro is used so I can access the 'globals' easily. Note: the
  307.     // variable containing the window must be theWindow, and it must be in
  308.     // scope at the time of the usage of this macro.
  309.     // Also, they aren't REALLY globals, becuase they're kept for EACH window,
  310.     // which is why I use the :1 notation, trying to keep this as small as
  311.     //    possible.)
  312.  
  313. //-----------------------------------------------------------------------------
  314.  
  315. typedef struct WDLDataRec {
  316.     WindowPeek            wdlWindow;
  317.     long                    wdlParam;
  318. } WDLDataRec, *WDLDataPtr;
  319.     // This information is used for the DeviceLoop we set up.
  320.  
  321. //*****************************************************************************
  322. //        Function Prototypes                                 
  323. //-----------------------------------------------------------------------------
  324.  
  325. void DoWInit( short varCode, WindowPeek theWindow, long param );
  326. void DoWDispose( WindowPeek theWindow, long param );
  327. long DoWHit( WindowPeek theWindow, long param );
  328. void DoWDraw ( WindowPeek theWindow, long param );
  329. void DoWCalcRgns ( WindowPeek theWindow, long param );
  330.  
  331. //*****************************************************************************
  332. //        Windoid Main Function                                                                     
  333. //-----------------------------------------------------------------------------
  334. //        This is the main entry point for all calls to this code resource. It
  335. //        dispatches to routines that correspond to the message it is given.
  336. //-----------------------------------------------------------------------------
  337.  
  338. pascal long main( short varCode, WindowPeek theWindow, 
  339.                             short message, long param ) {
  340.     GrafPtr        wpSavePort;
  341.     CGrafPtr        theCPort;
  342.     long            result;
  343.     Boolean        colorSystem;
  344.  
  345.     if ( colorSystem = (((message == wDraw) || (message == wHit)) 
  346.           && WindData.hasCQD) ) {
  347.         GetPort( &wpSavePort );
  348.         GetCWMgrPort( &theCPort );
  349.         SetPort( (GrafPtr)theCPort );
  350.     }
  351.         // This sets up the appropriate drawing environment, but only for those
  352.         // messages for which we actually need to draw.
  353.  
  354.     switch( message ) {
  355.         case wDraw:            DoWDraw( theWindow, param & 0xFFFF );
  356.                                 break;
  357.             // There's a tech note that says that for the draw message, only
  358.             // the low-order word of param is set correctly, so we should do
  359.             // this (& 0xFFFF) to make sure we're looking at the correct value.
  360.             
  361.         case wHit:            result = DoWHit( theWindow, param );        
  362.                                 break;
  363.         
  364.         case wCalcRgns:    DoWCalcRgns( theWindow, param );
  365.                                 break;
  366.         
  367.         case wNew:            DoWInit( varCode, theWindow, param );
  368.                                 break;
  369.         
  370.         case wDispose:        DoWDispose( theWindow, param );
  371.                                 break;
  372.  
  373.     //    case wGrow:            DoWGrow( theWindow, param );
  374.     //                            break;
  375.     //    case wDrawGIcon:    DoWDrawGIcon( theWindow, param );
  376.     //                            break;
  377.         // I don't allow of a grow box in a windoid. If you want one, you will
  378.         // have to implement these two routines.
  379.     }
  380.     
  381.     if ( colorSystem )
  382.         SetPort( wpSavePort );
  383.     
  384.     return result;
  385. }
  386.  
  387. //*****************************************************************************
  388. //        Environment-determining Routines                                                                             
  389. //-----------------------------------------------------------------------------
  390.     // These use SysEnvirons so we don't have to rely on Gestalt being available
  391.     // and so MPW won't include that code in our resource.
  392.  
  393. short HasSystem7() {
  394.     SysEnvRec    theWorld;
  395.     long            theSysVers = 0;
  396.     
  397.     if ( SysEnvirons( 1, &theWorld ) == noErr )
  398.         theSysVers = (long)theWorld.systemVersion;
  399.     
  400.     return( theSysVers >= 0x0700 );
  401. }
  402.  
  403. //-----------------------------------------------------------------------------
  404.  
  405. short HasCQDraw() {
  406.     SysEnvRec    theWorld;
  407.             
  408.     if ( (SysEnvirons( 1, &theWorld ) == noErr) && theWorld.hasColorQD )
  409.         return 1;
  410.         
  411.     return 0;
  412. }
  413.  
  414. //*****************************************************************************
  415. //        Color Mixing Routines                                                                     
  416. //-----------------------------------------------------------------------------
  417.  
  418. void GetWctbColor( short partCode, RGBColor *theColor ) {
  419.     // Given a partCode, return the RGBColor associated with it. (Using the
  420.     // default window color table.)
  421.  
  422.     AuxWinHandle    awHndl;
  423.     short                junkResult;
  424.  
  425.     junkResult = GetAuxWin( nil, &awHndl );
  426.     *theColor = (**(WCTabHandle)((**awHndl).awCTable)).ctTable[partCode].rgb;
  427. }
  428.  
  429. //-----------------------------------------------------------------------------
  430.  
  431. void SetWctbColor( short partCode ) {
  432.     RGBColor            theColor;
  433.  
  434.     GetWctbColor( partCode, &theColor );
  435.     RGBForeColor( &theColor );
  436. }
  437.  
  438. //-----------------------------------------------------------------------------
  439. #pragma processor 68020
  440.     // Note: this should be okay because this will only be called if we are
  441.     // doing System 7 color, which requires Color Quickdraw, which is only
  442.     // available on systems with 68020's or better. Again, this is done to
  443.     //    reduce code size. If it isn't compiled this way, several routines will
  444.     // be added to handle the long integer arithmetic. We would like to avoid
  445.     // that.
  446.  
  447. void MixColor( const RGBColor *lightColor, const RGBColor *darkColor, 
  448.                     short shade, RGBColor *result ) {
  449.     shade = 0x0F - shade;
  450.         // This is necessary because we give shades between light and
  451.         // dark (0% is light), but for colors, $0000 is black and $FFFF 
  452.         //    is dark.
  453.  
  454.     result->red        =  ((lightColor->red - darkColor->red) * shade / 15) 
  455.                             + darkColor->red;
  456.     result->green    =  ((lightColor->green - darkColor->green) * shade / 15)
  457.                             + darkColor->green;
  458.     result->blue    =  ((lightColor->blue - darkColor->blue) * shade / 15) 
  459.                             + darkColor->blue;
  460. }
  461.  
  462. #pragma processor 68000
  463. //-----------------------------------------------------------------------------
  464.  
  465. void AvgWctbColor( short light, short dark, short shade, 
  466.                          RGBColor *theColor ) {
  467.     // Mix two parts by the given shade, which is actually a value
  468.     // between 0 (0%) and 15 (100%), return the RGBColor.
  469.     
  470.     RGBColor            lightColor;
  471.     RGBColor            darkColor;
  472.  
  473.     GetWctbColor( light, &lightColor );
  474.     GetWctbColor( dark, &darkColor );
  475.     MixColor( &lightColor, &darkColor, shade, theColor );
  476. }
  477.  
  478. //*****************************************************************************
  479. //        Helper Functions
  480. //-----------------------------------------------------------------------------
  481.  
  482. void FrameBox( const Rect *theRect ) {
  483.     Rect tempRect = *theRect;
  484.     
  485.     FrameRect( theRect );
  486.     InsetRect( &tempRect, 1, 1 );
  487.     EraseRect( &tempRect );
  488. }
  489.  
  490. //*****************************************************************************
  491. //        Routines to get Rects for title bar parts                                             
  492. //-----------------------------------------------------------------------------
  493.  
  494. void GetTitleBar( WindowPeek theWindow, Rect *titleBar ) {
  495.     *titleBar = (**(theWindow->strucRgn)).rgnBBox;
  496.  
  497. #ifdef ALLOW_VERT
  498.     if (WindData.isHoriz) {                                        
  499. #endif
  500.             // Horizontal title bar
  501.             titleBar->bottom = titleBar->top + wpTitleHeight;
  502.             titleBar->right -= 1;                                // shadow compensation
  503. #ifdef ALLOW_VERT
  504.     } else {                                                            
  505.             // Vertical title bar
  506.             titleBar->right = titleBar->left + wpTitleHeight;
  507.             titleBar->bottom -= 1;                                 // shadow compensation
  508.     }
  509. #endif
  510. }
  511.  
  512. //-----------------------------------------------------------------------------
  513.  
  514. void GetCloseBox( WindowPeek theWindow, Rect *titleRect, Rect *theRect ) {
  515.     #pragma unused( theWindow )
  516.  
  517.     *theRect = *titleRect;
  518.  
  519.     InsetRect( theRect, 2, 2 );
  520. #ifdef ALLOW_VERT
  521.     if (WindData.isHoriz)
  522.         theRect->left += 4;
  523.     else
  524.         theRect->top += 4;
  525. #else
  526.     theRect->left += 4;
  527. #endif
  528.  
  529.     theRect->bottom = theRect->top + wpTitleHeight - 4;
  530.     theRect->right  = theRect->left + wpTitleHeight - 4;
  531. }
  532.  
  533. //-----------------------------------------------------------------------------
  534. #ifdef MFI_ZOOMBOX
  535.  
  536. void GetZoomBox( WindowPeek theWindow, Rect *titleRect, Rect *theRect ) {
  537.     *theRect = *titleRect;
  538.  
  539.     InsetRect( theRect, 2, 2 );
  540. #ifdef ALLOW_VERT
  541.     if ( WindData.isHoriz )                            // Horizontal titlebar
  542.         theRect->right -= 4;
  543.     else                                                    // Vertical titlebar
  544.         theRect->bottom -= 4;
  545. #else // always Horizontal
  546.     theRect->right -= 4;
  547. #endif
  548.  
  549.     theRect->top = theRect->bottom - wpTitleHeight + 4;
  550.     theRect->left = theRect->right - wpTitleHeight + 4;
  551. }
  552.  
  553. //*****************************************************************************
  554. //        SetZoomRects                                                     
  555. //-----------------------------------------------------------------------------
  556.     // This routine can be changed to do a window that zooms in another fashion
  557.     
  558. void SetZoomRects( WindowPeek theWindow ) {
  559.     Rect        theRect;
  560.     GrafPtr    savePort;
  561.     
  562.     if ( WindData.hasZoom ) {
  563.         GetPort( &savePort );
  564.         SetPort( (GrafPtr)theWindow );
  565.         theRect = theWindow->port.portRect;
  566.         LocalToGlobal( (Point*)&(theRect.top) );
  567.         LocalToGlobal( (Point*)&(theRect.bottom) );
  568.         SetPort( savePort );
  569.         
  570.         WindData.wState.stdState = theRect;
  571.         if ( WindData.isHoriz )                            // Horizontal titlebar
  572.             theRect.bottom = theRect.top + wpSmallZoom;
  573.         else                                                    // Vertical titlebar
  574.             theRect.right = theRect.left + wpSmallZoom;
  575.         WindData.wState.userState = theRect;
  576.             // the stdState and user state might be backwards from how they
  577.             // would normally be used by an application. Check this for your
  578.             // own use and change them if necessary.
  579.     }
  580. }
  581.  
  582. #endif
  583. //*****************************************************************************
  584. //        DoWInit -- Windoid initialization                                                     
  585. //-----------------------------------------------------------------------------
  586.  
  587. void DoWInit( short varCode, WindowPeek theWindow, long param ) {
  588.     #pragma unused( param )
  589.     
  590.     Handle zoomStuff;
  591.  
  592.     theWindow->spareFlag = false;
  593.     zoomStuff = NewHandle( sizeof(WindoidData) );
  594.     if ( zoomStuff ) {
  595.         theWindow->spareFlag        = true;
  596.         theWindow->dataHandle     = zoomStuff;
  597.         WindData.closeToggle     = 0;
  598.         WindData.hasCQD            = HasCQDraw();
  599.         WindData.isSystem7         = HasSystem7();
  600. #ifdef MACAPP_STYLE
  601.         WindData.isHoriz             = true;        // MacApp doesn't do vertical titlebars
  602.         WindData.ignoreHilite    = !((kMacApp_toggleTBar & varCode) != 0);
  603. #else
  604.         WindData.isHoriz             = ((7 & varCode) == 0);
  605.         WindData.ignoreHilite    = false;
  606. #endif
  607.  
  608. #ifdef MFI_ZOOMBOX
  609.         WindData.zoomToggle         = 0;
  610.     #ifdef MACAPP_STYLE                            // these constants are actually the same
  611.         WindData.hasZoom             = ((kMacApp_hasZoom & varCode) != 0);
  612.     #else
  613.         WindData.hasZoom             = ((zoomDocProc & varCode) != 0);
  614.     #endif
  615.         SetZoomRects( theWindow );
  616. #endif
  617.  
  618. #ifdef ALWAYS_HILITE
  619.         WindData.ignoreHilite    = true;
  620. #endif
  621.     }
  622. }
  623.  
  624. //*****************************************************************************
  625. //        DoWDispose -- Windoid disposal                                                         
  626. //-----------------------------------------------------------------------------
  627.  
  628. void DoWDispose( WindowPeek theWindow, long param ) {
  629.     #pragma unused( param )
  630.  
  631.     if ( theWindow->dataHandle )
  632.         DisposHandle( theWindow->dataHandle );
  633. }
  634.  
  635. //*****************************************************************************
  636. //        DoWHit -- Windoid hit routine                                                             
  637. //-----------------------------------------------------------------------------
  638.  
  639. long DoWHit( WindowPeek theWindow, long param ) {
  640.     Rect                    theStdRect;
  641.     Rect                    theUsrRect;
  642.     Rect                    titleRect;
  643.     Rect                    contentRect;
  644.     Rect                    theRect;
  645.     Point                    hitPt;
  646.     long                    result;
  647. #ifdef MFI_ZOOMBOX
  648.     short                    zoomedNorm;
  649. #endif
  650.  
  651.     hitPt.v = HiWord( param );
  652.     hitPt.h = LoWord( param );
  653.     
  654.     if ( PtInRgn( hitPt, theWindow->contRgn ) )
  655.         result = wInContent;
  656.     else {
  657.         GetTitleBar( theWindow, &titleRect );
  658.         if ( PtInRect( hitPt, &titleRect ) ) {
  659.             result = wInDrag;
  660.             if ( WindData.ignoreHilite || theWindow->hilited ) {
  661.                 GetCloseBox( theWindow, &titleRect, &theRect );
  662.                 if ( PtInRect( hitPt, &theRect ) )
  663.                     result = wInGoAway;
  664. #ifdef MFI_ZOOMBOX
  665.                 else if ( WindData.hasZoom ) {
  666.                     GetZoomBox( theWindow, &titleRect, &theRect );
  667.                     if ( PtInRect( hitPt, &theRect ) ) {
  668.                         contentRect = (**(theWindow->contRgn)).rgnBBox;
  669.                         
  670.                         if ( WindData.isHoriz )                    // Horizontal
  671.                             zoomedNorm = ( (contentRect.bottom - contentRect.top)
  672.                                                 > (wpSmallZoom + 3) );
  673.                         else                                            // Vertical
  674.                             zoomedNorm = ( (contentRect.right - contentRect.left)
  675.                                                 > (wpSmallZoom + 3) );
  676.                         
  677.                         if ( zoomedNorm )                            // Make Small
  678.                             result = wInZoomIn;
  679.                         else                                            // Make Normal
  680.                             result = wInZoomOut;
  681.                         
  682.                         // Calculate Offset for Zoom Rects
  683.                         theStdRect = WindData.wState.stdState;
  684.                         theUsrRect = WindData.wState.userState;
  685.                         
  686.                         OffsetRect( &(WindData.wState.stdState), contentRect.left
  687.                                        - theStdRect.left, contentRect.top - theStdRect.top );
  688.                         OffsetRect( &(WindData.wState.userState), contentRect.left
  689.                                        - theUsrRect.left, contentRect.top - theUsrRect.top );
  690.                     }
  691.                 }
  692. #endif
  693.             }
  694.         } else
  695.             result = wNoHit;
  696.     }
  697.     return result;
  698. }    // DoWHit
  699.  
  700. //*****************************************************************************
  701. //        DoWDraw -- Windoid drawing routines                                                     
  702. //-----------------------------------------------------------------------------
  703.  
  704. void DrawCloseBox( short variation, Rect *theRect ) {
  705.     RGBColor theColor;
  706.     Rect        tempRect;
  707.  
  708.     switch ( variation ) {
  709.         case blackandwhite:
  710.             FrameBox( theRect );
  711.             break;
  712.         
  713.         case sys6color:
  714.             SetWctbColor( wHiliteColor );
  715.             GetWctbColor( wTitleBarColor, &theColor );
  716.             RGBBackColor( &theColor );
  717.             FrameBox( theRect );
  718.             break;
  719.         
  720.         case sys7color:
  721.             SetWctbColor( wTingeLight );
  722.             PaintRect( theRect );
  723.         
  724.             SetWctbColor( wTingeDark );
  725.         
  726.             MoveTo( theRect->right - 1, theRect->top );
  727.             LineTo( theRect->left, theRect->top );
  728.             LineTo( theRect->left, theRect->bottom - 1 );
  729.         
  730.             MoveTo( theRect->right - 2, theRect->top + 2 );
  731.             LineTo( theRect->right - 2, theRect->bottom - 2 );
  732.             LineTo( theRect->left + 2, theRect->bottom - 2 );
  733.         
  734.             AvgWctbColor( wHiliteColorLight, wHiliteColorDark, 
  735.                               wCloseBoxColor, &theColor );
  736.             RGBForeColor( &theColor );
  737.             tempRect = *theRect;
  738.             InsetRect( &tempRect, 2, 2 );
  739.             PaintRect( &tempRect );
  740.             
  741.             break;
  742.     }
  743.         
  744. }
  745.  
  746. //*****************************************************************************
  747. //        DrawZoomBox -- Draw zoom box
  748. //-----------------------------------------------------------------------------
  749. #ifdef MFI_ZOOMBOX
  750.  
  751. void DrawZoomBox( short variation, Rect *theRect ) {
  752.     Rect        tempRect;
  753.     RGBColor theColor;
  754.  
  755.     switch ( variation ) {
  756.         case blackandwhite:
  757.         case sys6color:
  758.             if ( variation != blackandwhite ) {
  759.                 SetWctbColor( wHiliteColor );
  760.                 GetWctbColor( wTitleBarColor, &theColor );
  761.                 RGBBackColor( &theColor );
  762.             }            
  763.             FrameBox( theRect );
  764.             tempRect = *theRect;
  765.             tempRect.bottom -= 3;
  766.             tempRect.right -= 3;
  767.             FrameRect( &tempRect );
  768.             break;
  769.         
  770.         case sys7color:
  771.             DrawCloseBox( variation, theRect );
  772.             SetWctbColor( wTingeDark );
  773.         
  774.             MoveTo(theRect->right - 4, theRect->top + 2);
  775.             LineTo(theRect->right - 4, theRect->bottom - 4);
  776.             LineTo(theRect->left + 2, theRect->bottom - 4);
  777.             break;
  778.     }
  779. }
  780.  
  781. #endif
  782. //*****************************************************************************
  783. //        DrawXedBox -- Draw close or zoom box with an X in it (or inverted in B&W)
  784. //-----------------------------------------------------------------------------
  785.  
  786. void DrawXedBox( short variation, Rect *theRect ) {
  787.     RGBColor theColor;
  788.  
  789.     switch ( variation ) {
  790.         case blackandwhite:
  791.             PaintRect( theRect );
  792.             break;
  793.             
  794.         case sys6color:
  795.             SetWctbColor( wHiliteColor );
  796.             PaintRect( theRect );
  797.             break;
  798.             
  799.         case sys7color:
  800.             AvgWctbColor( wTingeLight, wTingeDark, wXedBoxPct, &theColor );
  801.             RGBForeColor( &theColor );
  802.             PaintRect( theRect );
  803.             
  804.             SetWctbColor( wFrameColor );
  805.             FrameRect( theRect );
  806.         
  807.             MoveTo( theRect->left, theRect->top );                        // Draw the 'X'
  808.             LineTo( theRect->right - 1, theRect->bottom - 1 );
  809.             MoveTo( theRect->right - 1, theRect->top );
  810.             LineTo( theRect->left, theRect->bottom - 1 );
  811.             break;
  812.     }
  813. }
  814.  
  815. //*****************************************************************************
  816. //        DrawTitlePat -- Draw pattern into the title bar
  817. //-----------------------------------------------------------------------------
  818.  
  819. void DrawTitlePatPat( Rect titleRect ) {
  820.     // This routine actually draws the pattern into the titlebar. Note: it
  821.     // takes a Rect as a parameter (not by address) because it goes ahead and
  822.     // modifies it. I figured this was no worse than needing to copy it into
  823.     // a local variable, so I went ahead and did it this way.
  824.  
  825.     Pattern    titlePat;
  826.     Point        corner;
  827.     char        *patPtr;
  828.     char        patChar1;
  829.     char        patChar2;
  830.     short        i;
  831.     
  832.     SetPt( &corner, titleRect.left, titleRect.top );
  833.     LocalToGlobal( &corner );
  834.  
  835.     if ( corner.v % 2 == 0 ) {    
  836.         patChar1 = 0x55;
  837.         patChar2 = 0x00;
  838.     } else { 
  839.         patChar1 = 0x00;
  840.         patChar2 = 0x55;
  841.     }
  842.     if ( corner.h % 2 == 0 ) {
  843.         patChar1 = patChar1 << 1;
  844.         patChar2 = patChar2 << 1;
  845.     }
  846.     
  847.     patPtr = (char *)&titlePat;
  848.     for ( i = 0 ; i < 8 ; i += 2 ) {
  849.         patPtr[i] = patChar1;
  850.         patPtr[i+1] = patChar2;
  851.     }
  852.     // Choose correct pattern, depending on position of window in global
  853.     // coordinates.
  854.  
  855.     InsetRect( &titleRect, 1, 1 );
  856.     FillRect( &titleRect, (ConstPatternParam)&titlePat );
  857. }
  858.  
  859. //-----------------------------------------------------------------------------
  860.  
  861. void DrawTitlePat( short variation, Rect *titleRect ) {
  862.     RGBColor    theColor;
  863.  
  864.     switch ( variation ) {
  865.         case blackandwhite:
  866.             ForeColor( blackColor );
  867.             BackColor( whiteColor );
  868.             break;
  869.             
  870.         case sys6color:
  871.             SetWctbColor( wHiliteColor );
  872.             GetWctbColor( wTitleBarColor, &theColor );
  873.             RGBBackColor( &theColor );
  874.             break;
  875.  
  876.         case sys7color:
  877.             AvgWctbColor( wHiliteColorLight, wHiliteColorDark, 
  878.                               wTitleBarLightPct, &theColor );
  879.             RGBBackColor( &theColor );
  880.             AvgWctbColor( wHiliteColorLight, wHiliteColorDark, 
  881.                               wTitleBarDarkPct, &theColor );
  882.             RGBForeColor( &theColor );
  883.             break;
  884.     }
  885.             
  886.     DrawTitlePatPat( *titleRect );
  887. }
  888.  
  889. //*****************************************************************************
  890. //        CheckDisplay -- Check to see if we are using color title bars
  891. //-----------------------------------------------------------------------------
  892.  
  893. Boolean CheckAvailable( short light, short dark, short count, short *ramp ) {
  894.     // Given a light and dark index value, a count, and and an array of
  895.     // 'percentage' values (0x0 to 0xF, or 0 to 15), see if each of the
  896.     // values in the ramp maps to a different color on the screen. If not,
  897.     // we need to use black-and-white.
  898.     
  899.     RGBColor    theColor;
  900.     short        i;
  901.     short        result = true;
  902.     short        colorIndex = -1;
  903.     short        lastIndex;
  904.                 
  905.     for ( i = 0 ; (i < count) && (result == true) ; i++ ) {
  906.         AvgWctbColor( light, dark, ramp[i], &theColor );    
  907.         lastIndex = colorIndex;
  908.         colorIndex = Color2Index( &theColor );
  909.         if ( (i > 0) && (colorIndex == lastIndex) )
  910.             result = false;
  911.     }
  912.     return result;
  913. }
  914.  
  915. //-----------------------------------------------------------------------------
  916.  
  917. short CheckDisplay( short theDepth, short deviceFlags, 
  918.                           GDHandle targetDevice, WindowPeek theWindow ) {
  919.     Boolean    inColor;
  920.     short        result;
  921.     RGBColor    testColor;
  922.     GDHandle    saveDevice;
  923.     short        list[5];
  924.         // Make sure this array is allcated big enough for the largest ramp.
  925.         
  926.     inColor = WindData.hasCQD && (deviceFlags & (0x0001 << gdDevType));
  927.     
  928.     result = blackandwhite;                    // assume Black and White
  929.     if ( (theDepth >= 8) || (!inColor && (theDepth >= 4)) ) {
  930.         if ( !WindData.isSystem7 )
  931.             result = sys6color;                // System 6.0.x Color
  932.         else {
  933.             GetWctbColor( wTingeLight, &testColor );
  934.             if ( testColor.red && testColor.green && testColor.blue ) 
  935.                 // check for B&W control panel setting, otherwise:
  936.                 result = sys7color;            // System 7.0 Color
  937.         }
  938.     }
  939.     // Note: Since I didn't find another way to see if the user had changed
  940.     // the settings in the Color control panel to the Black-and-white setting,
  941.     // I actually check to see if the rgb components of the light tinge color
  942.     // are non-zero (which seemed to be the case with that setting). 
  943.     
  944.     if ( (result == sys7color) && (theDepth == 8) ) {
  945.         result = blackandwhite;
  946.         saveDevice = GetGDevice();
  947.         SetGDevice( targetDevice );
  948.         list[0] = 0x00;
  949.         list[1] = 0x07;
  950.         list[2] = 0x08;
  951.         list[3] = 0x0A;
  952.         list[4] = 0x0D;
  953.         if ( CheckAvailable( wHiliteColorLight, wHiliteColorDark, 5, list ) ) {
  954.             list[0] = 0x00;
  955.             list[1] = 0x01;
  956.             list[2] = 0x04;
  957.             if ( CheckAvailable( wTitleBarLight, wTitleBarDark, 3, list ) ) {
  958.                 list[0] = 0x00;
  959.                 list[1] = 0x04;
  960.                 list[2] = 0x0F;
  961.                 if ( CheckAvailable( wTingeLight, wTingeDark, 3, list ) )
  962.                     result = sys7color;
  963.             }
  964.         }
  965.         SetGDevice( saveDevice );
  966.     }
  967.     // This part checks to see if there are 'enough' colors to draw the 
  968.     //    title bar in color under System 7. It is supposed to do so in the
  969.     // same way that Apple's system WDEF does. I essentially took the 
  970.     // assembly code that Apple released and tried to make this use the
  971.     // same algorithm. Note: the values in list for the first CheckAvailable
  972.     // call are set up in the variable declaration in the top of the routine.
  973.     // Don't you just LOVE what C lets you do?
  974.  
  975.     return result;
  976. }
  977.  
  978. //*****************************************************************************
  979.  
  980. pascal void WindoidDrawLoop( short depth, short deviceFlags, 
  981.                                       GDHandle targetDevice, WDLDataPtr userData) {
  982.     #pragma unused( targetDevice )
  983.     // This routine actually does the real work of the drawing of stuff into
  984.     // the window.
  985.  
  986.     Rect            titleRect;
  987.     Rect             tempRect;
  988.     RGBColor        theColor;
  989.     WindowPeek    theWindow;
  990.     short            fancy;
  991.  
  992.     theWindow = userData->wdlWindow;
  993.     fancy = CheckDisplay(depth, deviceFlags, targetDevice, theWindow);
  994.     
  995.     if ( theWindow->visible )
  996.         switch ( userData->wdlParam ) {
  997.             case 0:
  998.                 BackColor( whiteColor );
  999.                 
  1000.                 // DRAW TITLEBAR
  1001.                 GetTitleBar( theWindow, &titleRect );
  1002.                 if ( fancy == sys7color )
  1003.                     if ( WindData.ignoreHilite || theWindow->hilited )
  1004.                         SetWctbColor( wFrameColor );
  1005.                     else {
  1006.                         AvgWctbColor( wHiliteColorLight, wHiliteColorDark,
  1007.                                           wInactiveFramePct, &theColor );
  1008.                         RGBForeColor( &theColor );
  1009.                     }
  1010.                 else if ( fancy == sys6color )
  1011.                     SetWctbColor( wFrameColor );
  1012.                 else
  1013.                     ForeColor( blackColor );
  1014.                 FrameRect(&titleRect);
  1015.                 
  1016.                 if ( WindData.ignoreHilite || theWindow->hilited )
  1017.                     DrawTitlePat( fancy, &titleRect );
  1018.                 else {
  1019.                     tempRect = titleRect;
  1020.                     InsetRect( &tempRect,1,1 );
  1021.                     EraseRect( &tempRect );
  1022.                 }
  1023.                 
  1024.                 if ( WindData.ignoreHilite || theWindow->hilited ) {
  1025.                 
  1026.                     // DRAW CLOSE BOX
  1027.                     if ( theWindow->goAwayFlag ) {    
  1028.                         GetCloseBox( theWindow, &titleRect, &tempRect );
  1029.                         DrawCloseBox( fancy, &tempRect );
  1030.                     }                                                
  1031.                         // Note: I have seen at least one windoid WDEF that is used
  1032.                         // by some applications that does not utilize this flag.
  1033.                         // In that case, I think it always had a close box (or it
  1034.                         // might even have used the varcode to determine this, but
  1035.                         // that wouldn't seem to be a good thing to do). Anyway, if
  1036.                         // you always want the close box, just comment out the 'if'
  1037.                         // line (and the close brace line) above.
  1038.  
  1039. #ifdef MFI_ZOOMBOX
  1040.                     // DRAW ZOOM BOX
  1041.                     if ( WindData.hasZoom ) {
  1042.                         GetZoomBox( theWindow, &titleRect, &tempRect );
  1043.                         DrawZoomBox( fancy, &tempRect );
  1044.                     }
  1045. #endif
  1046.                 }
  1047.  
  1048.                 // DRAW CONTENT FRAME AND SHADOW
  1049.                 tempRect = (**(theWindow->strucRgn)).rgnBBox;
  1050.  
  1051.                 tempRect.bottom = tempRect.bottom - 1;
  1052.                 tempRect.right = tempRect.right - 1;
  1053.                 if (fancy == sys7color)
  1054.                     if ( WindData.ignoreHilite || theWindow->hilited )
  1055.                         SetWctbColor( wFrameColor );
  1056.                     else {
  1057.                         AvgWctbColor( wHiliteColorLight, wHiliteColorDark,
  1058.                                           wInactiveFramePct, &theColor );
  1059.                         RGBForeColor( &theColor );
  1060.                     }
  1061.                 else if ( fancy == sys6color )
  1062.                     SetWctbColor( wFrameColor );
  1063.                 else                                             // black-and-white
  1064.                     ForeColor( blackColor );
  1065.                 FrameRect( &tempRect );
  1066.                     // If the window is not hilited, this will use a gray shade
  1067.                     // to draw the window outline in System 7 color.
  1068.                 
  1069.                 ForeColor( blackColor );                // draw shadow
  1070.                 MoveTo( tempRect.right, tempRect.top+1 );
  1071.                 LineTo( tempRect.right, tempRect.bottom );
  1072.                 LineTo( tempRect.left + 1, tempRect.bottom );
  1073.             break;
  1074.  
  1075.             case wInGoAway:                                // toggle go-away
  1076.                 GetTitleBar( theWindow, &titleRect );
  1077.                 GetCloseBox( theWindow, &titleRect, &tempRect );
  1078.                 if ( WindData.closeToggle )
  1079.                     DrawCloseBox( fancy, &tempRect );
  1080.                 else
  1081.                     DrawXedBox( fancy, &tempRect );
  1082.             break;
  1083.         
  1084. #ifdef MFI_ZOOMBOX
  1085.             default:
  1086.                 if ( WindData.hasZoom ) {                            // toggle zoom box
  1087.                     GetTitleBar( theWindow, &titleRect );
  1088.                     GetZoomBox( theWindow, &titleRect, &tempRect );
  1089.                     if ( WindData.zoomToggle )
  1090.                         DrawZoomBox( fancy, &tempRect );
  1091.                     else
  1092.                         DrawXedBox( fancy, &tempRect );
  1093.                 }
  1094. #endif
  1095.     }
  1096.     ForeColor( blackColor );
  1097.     BackColor( whiteColor );
  1098. } // WindoidDrawLoop
  1099.  
  1100. //-----------------------------------------------------------------------------
  1101.  
  1102. void DoWDraw( WindowPeek theWindow, long param ) {
  1103.     WDLDataRec        theUserData;
  1104.     GrafPtr             savePort;
  1105.     RgnHandle         drawRgn;
  1106.     Rect                theRect;
  1107.     GDHandle            theDevice;
  1108.     PixMapHandle    thePixMap;
  1109.     short                theDepth;
  1110.     short                inColor;
  1111.  
  1112.     GetPort( &savePort );
  1113.     SetPort( (GrafPtr)theWindow );
  1114.     drawRgn = theWindow->strucRgn;
  1115.     SetPort( savePort );
  1116.     
  1117.     theUserData.wdlWindow    = theWindow;
  1118.     theUserData.wdlParam        = param;
  1119.  
  1120.     if ( WindData.isSystem7 ) {
  1121.         DeviceLoop( drawRgn, (DeviceLoopDrawingProcPtr)WindoidDrawLoop, 
  1122.                         (long)&theUserData, (DeviceLoopFlags)0 );
  1123.     } else {
  1124.         theDepth = 1;
  1125.         inColor = 0;
  1126.         if ( theWindow && WindData.hasCQD ) {
  1127.             GetPort( &savePort );
  1128.             SetPort( (GrafPtr)theWindow );
  1129.             theRect = ((GrafPtr)theWindow)->portRect;
  1130.             LocalToGlobal( (Point*)&theRect.top );
  1131.             LocalToGlobal( (Point*)&theRect.bottom );
  1132.             theDevice = GetMaxDevice( &theRect );
  1133.             SetPort( savePort );
  1134.             
  1135.             if ( theDevice ) {
  1136.                 thePixMap = (**theDevice).gdPMap;
  1137.                 theDepth = (**thePixMap).pixelSize;
  1138.                 WindoidDrawLoop( theDepth, (**theDevice).gdFlags, 
  1139.                                       theDevice, &theUserData );
  1140.             } else 
  1141.                 WindoidDrawLoop( 1, 0, nil, &theUserData );
  1142.                 
  1143.             // Do this for pre-System 7. we call WindoidDrawLoop directly, giving
  1144.             // it the information on the device with maximum depth, hoping that
  1145.             // the results will be okay. Only reason it might not be is if you
  1146.             // have a System 6 color window that crosses two monitors that have
  1147.             // differing environments where one doesn't have enough colors to
  1148.             // show the color version. Here, the problem will be only cosmetic,
  1149.             // though. Note: I could have done my own device loop for this case,
  1150.             // but I figured it wasn't common enough for the expense.
  1151.         } else {
  1152.             WindoidDrawLoop( 1, 0, nil, &theUserData );
  1153.             
  1154.             // Do this for 68000's
  1155.         }
  1156.     }
  1157.  
  1158.     if ( theWindow->visible )
  1159.         switch ( param ) {
  1160.             case 0:
  1161.                 break;
  1162.  
  1163.             case wInGoAway:                                // toggle go-away
  1164.                 WindData.closeToggle = !(WindData.closeToggle);
  1165.                 break;
  1166.             
  1167. #ifdef MFI_ZOOMBOX
  1168.             default:
  1169.                 if ( WindData.hasZoom )                    // toggle zoom box
  1170.                     WindData.zoomToggle = !(WindData.zoomToggle);
  1171. #endif
  1172.     }
  1173.     if ( WindData.hasCQD ) {        // restore the color environment to default
  1174.         ForeColor( blackColor );
  1175.         BackColor( whiteColor );
  1176.     }
  1177.  
  1178. } // DoWDraw
  1179.  
  1180. //*****************************************************************************
  1181. //        DoWCalcRgns -- Windoid region calculating routine                                 
  1182. //-----------------------------------------------------------------------------
  1183.  
  1184. void DoWCalcRgns( WindowPeek theWindow, long param ) {
  1185.     #pragma unused( param )
  1186.     
  1187.     short            hOfst, vOfst;
  1188.     Rect            theContentRect;
  1189.     Rect            theStructRect;
  1190.     Rect            tempRect;
  1191.     RgnHandle    tempRgn;
  1192.     GrafPtr        savePort;
  1193.  
  1194.     GetPort( &savePort );
  1195.     SetPort( (GrafPtr)theWindow );
  1196.     theContentRect = ((GrafPtr)theWindow)->portRect;
  1197.     hOfst = ((GrafPtr)theWindow)->portBits.bounds.left;
  1198.     vOfst = ((GrafPtr)theWindow)->portBits.bounds.top;
  1199.     OffsetRect( &theContentRect, -hOfst, -vOfst );
  1200.     RectRgn( theWindow->contRgn, &theContentRect );
  1201.     theStructRect = theContentRect;
  1202.     InsetRect( &theStructRect, -1, -1 );
  1203.     if ( WindData.isHoriz )
  1204.         theStructRect.top -= wpTitleHeight - 1;
  1205.     else
  1206.         theStructRect.left -= wpTitleHeight - 1;
  1207.     RectRgn( theWindow->strucRgn, &theStructRect );
  1208.     tempRect = theStructRect;
  1209.     OffsetRect( &tempRect, 1, 1 );
  1210.     tempRgn = NewRgn();
  1211.     RectRgn( tempRgn, &tempRect );
  1212.     UnionRgn( tempRgn, theWindow->strucRgn, theWindow->strucRgn );
  1213.     DisposeRgn( tempRgn );
  1214.     
  1215.     SetPort( savePort );
  1216. }
  1217.  
  1218. //*****************************************************************************